package com.cn.encryp;

import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @description: ECC非对称加密算法
 * @Author 朱明川
 * 其它选择：ECC（椭圆曲线数字签名算法（ECDSA））
 * RSA 与 DSA 各有优缺点，那有没一个更好的选择呢？答案是肯定的，ECC（Elliptic Curves Cryptography）：椭圆曲线算法。
 * todo ECC 与 RSA 相比，有以下的优点：
 * （1）相同密钥长度下，安全性能更高，如160位ECC已经与1024位RSA、DSA有相同的安全强度。
 * （2）计算量小，处理速度快，在私钥的处理速度上（解密和签名），ECC远 比RSA、DSA快得多。
 * （3）存储空间占用小 ECC的密钥尺寸和系统参数与RSA、DSA相比要小得多， 所以占用的存储空间小得多。
 * （4）带宽要求低使得ECC具有广泛得应用前景。
 * 在 ssh-keygen 中，ECC 算法的相应参数是 “-t ecdsa”。可惜的是由于椭圆曲线算法只有在较新版本的 openssl 与 ssh-keygen 中才被支持，
 * 而无法得到普遍使用而去完全替代 RSA/DSA。不过由于椭圆曲线算法的优点，使其取代 RSA/DSA 而成为新一代通用的非对称加密算法成为可能，
 * 至少 SET 协议的制定者们已经把它作为下一代 SET 协议中缺省的公钥密码算法了。
 * todo DSA签名快，验签慢，和RSA刚刚相反。ECC是更好的选择。
 */
public class ECC {

    public static byte[] encrypt(String plainText, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance("ECIES", "BC");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        return cipher.doFinal(plainText.getBytes());
    }

    public static byte[] decrypt(byte[] encryptedBytes, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance("ECIES", "BC");
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        return cipher.doFinal(encryptedBytes);
    }

    public static void main(String[] args) throws Exception {
        // 添加Bouncy Castle作为加密提供程序
        Security.addProvider(new BouncyCastleProvider());

        //随机数
        SecureRandom secureRandom = new SecureRandom(UUID.randomUUID().toString().getBytes(StandardCharsets.UTF_8));

        // 生成密钥对
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC", "BC");
        //初始化密钥对生成器（指定密钥长度, 使用uuid的安全随机数源）
        //192 -> prime192v1;239 -> prime239v1;256 -> prime256v1; 224->P-224;  384->P-384;  521->P-521;
        keyPairGenerator.initialize(521, secureRandom);
        //自定义椭圆曲线参数
        //keyPairGenerator.initialize(ECNamedCurveTable.getParameterSpec("secp256r1"), secureRandom);

        //随机生成一对密钥（包含公钥和私钥）
        KeyPair keyPair = keyPairGenerator.generateKeyPair();

        // 获取公钥和私钥
        PublicKey publicKey = keyPair.getPublic();
        System.out.println("公钥: " + Base64.getEncoder().encodeToString(publicKey.getEncoded()));
        PrivateKey privateKey = keyPair.getPrivate();
        System.out.println("私钥: " + Base64.getEncoder().encodeToString(privateKey.getEncoded()));

        // 明文
        String plainText = "我是明文123456";

        // 加密
        byte[] encryptedBytes = encrypt(plainText, publicKey);
        String encryptedText = Base64.getEncoder().encodeToString(encryptedBytes);
        System.out.println("Encrypted Text: " + encryptedText);

        // 解密
        byte[] decryptedBytes = decrypt(encryptedBytes, privateKey);
        String decryptedText = new String(decryptedBytes);
        System.out.println("Decrypted Text: " + decryptedText);
    }

}
